home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -in_the_mag- / emulation / amiga / uae-0.7.0b2 / src / gtkui.c < prev    next >
C/C++ Source or Header  |  1998-01-20  |  13KB  |  487 lines

  1. /*
  2.  * UAE - the Un*x Amiga Emulator
  3.  *
  4.  * Yet Another User Interface for the X11 version
  5.  *
  6.  * Copyright 1997 Bernd Schmidt
  7.  * 
  8.  * The Tk GUI doesn't work.
  9.  * The X Forms Library isn't available as source, and there aren't any
  10.  * binaries compiled against glibc
  11.  *
  12.  * So let's try this...
  13.  */
  14.  
  15. #include "sysconfig.h"
  16. #include "sysdeps.h"
  17.  
  18. #include "config.h"
  19. #include "options.h"
  20. #include "uae.h"
  21. #include "memory.h"
  22. #include "custom.h"
  23. #include "readcpu.h"
  24. #include "gui.h"
  25. #include "newcpu.h"
  26. #include "threaddep/penguin.h"
  27.  
  28. #include <gtk/gtk.h>
  29.  
  30. static GtkWidget *disk_insert_widget[4], *disk_eject_widget[4], *disk_text_widget[4];
  31. static char *led_bufs[5];
  32. static int gcs_initialized = 0;
  33.  
  34. static char *disk_string[4];
  35. static char *new_disk_string[4];
  36.  
  37. static GtkWidget *led_widgets[5];
  38.  
  39. static int nr_for_led (GtkWidget *led)
  40. {
  41.     int i;
  42.     i = 0;
  43.     while (led_widgets[i] != led)
  44.     i++;
  45.     return i;
  46. }
  47.  
  48. static smp_comm_pipe to_gui_pipe, from_gui_pipe;
  49. static uae_sem_t gui_sem, gui_quit_sem;
  50.  
  51. static volatile int quit_gui = 0, quitted_gui = 0;
  52.  
  53. static void enable_disk_buttons (int enable);
  54.  
  55. static unsigned int prevledstate;
  56.  
  57. static void draw_led (int nr)
  58. {
  59.     GtkWidget *thing = led_widgets[nr];
  60.     int r = 0, g = 0, b = 0;
  61.     int i, j, k;
  62.     char *buf = led_bufs[nr];
  63.     
  64.     if (buf == 0)
  65.     return;
  66.     if (gui_ledstate & (1 << nr)) {
  67.     if (nr == 4)
  68.         r = 0xCC;
  69.     else
  70.         r = 0x88, g = 0xFF;
  71.     }
  72.     printf ("%dx%d\n", thing->allocation.width, thing->allocation.height);
  73.  
  74.     for (j = k = 0; j < thing->allocation.width; j++)
  75.     buf[k++] = r, buf[k++] = g, buf[k++] = b;
  76.     for (i = 0; i < thing->allocation.height; i++) {
  77.     gtk_preview_draw_row (GTK_PREVIEW (thing), buf, 0, i, thing->allocation.width);
  78.     }
  79.     gtk_widget_draw (thing, 0);
  80. }
  81.  
  82. static int my_idle (void)
  83. {
  84.     unsigned int leds = gui_ledstate;
  85.     int i;
  86.  
  87.     /*printf("...\n");*/
  88.     if (quit_gui) {
  89.     printf("Foo...\n");
  90.     gtk_main_quit ();
  91.     goto out;
  92.     }
  93.     while (comm_pipe_has_data (&to_gui_pipe)) {
  94.     int cmd = read_comm_pipe_int_blocking (&to_gui_pipe);
  95.     int n;
  96.     /*printf ("cmd %d\n", cmd);*/
  97.     switch (cmd) {
  98.      case 0:
  99.         n = read_comm_pipe_int_blocking (&to_gui_pipe);
  100.         gtk_label_set (GTK_LABEL (disk_text_widget[n]), currprefs.df[n]);
  101.         break;
  102.     }
  103.     }
  104.     
  105.     for (i = 0; i < 5; i++) {
  106.     unsigned int mask = 1 << i;
  107.     GtkWidget *thing;
  108.     int on = leds & mask;
  109.  
  110.     if (on == (prevledstate & mask))
  111.         continue;
  112.  
  113.     printf(": %d %d\n", i, on);
  114.     draw_led (i);
  115.     }
  116.     prevledstate = leds;
  117. out:
  118.     return 1;
  119. }
  120.  
  121. static void did_reset (void)
  122. {
  123.     if (quit_gui)
  124.     return;
  125.     
  126.     write_comm_pipe_int (&from_gui_pipe, 2, 1);
  127. }
  128.  
  129. static void did_debug (void)
  130. {
  131.     if (quit_gui)
  132.     return;
  133.     
  134.     write_comm_pipe_int (&from_gui_pipe, 3, 1);
  135. }
  136.  
  137. static void did_quit (void)
  138. {
  139.     if (quit_gui)
  140.     return;
  141.     
  142.     write_comm_pipe_int (&from_gui_pipe, 4, 1);
  143. }
  144.  
  145. static void did_eject (int n)
  146.     if (quit_gui)
  147.     return;
  148.     
  149.     write_comm_pipe_int (&from_gui_pipe, 0, 0);
  150.     write_comm_pipe_int (&from_gui_pipe, n, 1);
  151. }
  152.  
  153. static int filesel_active = -1;
  154. static GtkWidget *selector;
  155.  
  156. static void did_close_insert (GtkObject *o, GtkWidget *w)
  157. {
  158.     filesel_active = -1;
  159.     enable_disk_buttons (1);
  160. }
  161.  
  162. static void did_cancel_insert (GtkObject *o)
  163. {
  164.     did_close_insert (o, GTK_WIDGET (o));
  165.     gtk_widget_destroy (GTK_WIDGET (o));
  166. }
  167.  
  168. static void did_insert_select (GtkObject *o)
  169. {
  170.     char *s = gtk_file_selection_get_filename (GTK_FILE_SELECTION (selector));
  171.     
  172.     if (quit_gui)
  173.     return;
  174.     
  175.     uae_sem_wait (&gui_sem);
  176.     if (new_disk_string[filesel_active] != 0)
  177.     free (new_disk_string[filesel_active]);
  178.     new_disk_string[filesel_active] = strdup (s);
  179.     uae_sem_post (&gui_sem);
  180.     write_comm_pipe_int (&from_gui_pipe, 1, 0);
  181.     write_comm_pipe_int (&from_gui_pipe, filesel_active, 1);
  182.     did_cancel_insert (o);
  183. }
  184.  
  185. static void did_insert (int n)
  186. {
  187.     char buffer[100];
  188.  
  189.     if (filesel_active != -1)
  190.     return;
  191.     filesel_active = n;
  192.     enable_disk_buttons (0);
  193.  
  194.     sprintf (buffer, "Select a disk image file for DF%d", n);
  195.     selector = gtk_file_selection_new (buffer);
  196.     gtk_signal_connect (GTK_OBJECT (selector), "destroy",
  197.             (GtkSignalFunc) did_close_insert, selector);
  198.  
  199.     gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (selector)->ok_button),
  200.                    "clicked", (GtkSignalFunc) did_insert_select,
  201.                    GTK_OBJECT (selector));
  202.     gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (selector)->cancel_button),
  203.                    "clicked", (GtkSignalFunc) did_cancel_insert,
  204.                    GTK_OBJECT (selector));
  205.  
  206.     printf("%p\n", selector);
  207.     gtk_widget_show (selector);
  208. }
  209.  
  210. static void did_eject_0 (void) { did_eject (0); }
  211. static void did_eject_1 (void) { did_eject (1); }
  212. static void did_eject_2 (void) { did_eject (2); }
  213. static void did_eject_3 (void) { did_eject (3); }
  214.  
  215. static void did_insert_0 (void) { did_insert (0); }
  216. static void did_insert_1 (void) { did_insert (1); }
  217. static void did_insert_2 (void) { did_insert (2); }
  218. static void did_insert_3 (void) { did_insert (3); }
  219.  
  220. static void enable_disk_buttons (int enable)
  221. {
  222.     int i;
  223.     for (i = 0; i < 4; i++) {
  224.     gtk_widget_set_sensitive (disk_insert_widget[i], enable);
  225.     gtk_widget_set_sensitive (disk_eject_widget[i], enable);
  226.     }
  227. }
  228.  
  229. static gint driveled_event (GtkWidget *thing, GdkEvent *event)
  230. {
  231.     gint x, y;
  232.     GtkStyle *style;
  233.     int lednr = nr_for_led (thing);
  234.  
  235.     switch (event->type) {
  236.      case GDK_MAP:
  237.     draw_led (lednr);
  238.     break;
  239.      case GDK_EXPOSE:
  240.     if (led_bufs[lednr] == 0) {
  241.         printf ("- %d\n", thing->allocation.width);
  242.         led_bufs[lednr] = (char *)xmalloc (3 * thing->allocation.width);
  243.         draw_led (lednr);
  244.     }
  245.     break;
  246.      default:
  247.     break;
  248.     }
  249.  
  250.   return 0;
  251. }
  252.  
  253. static GtkWidget *make_led (int nr)
  254. {
  255.     GtkWidget *subframe, *the_led, *thing;
  256.     
  257.     the_led = gtk_vbox_new (FALSE, 0);
  258.     gtk_widget_set_usize (the_led, 20, -1);
  259.     gtk_widget_show (the_led);
  260.  
  261.     thing = gtk_preview_new (GTK_PREVIEW_COLOR);
  262.     gtk_box_pack_start (GTK_BOX (the_led), thing, TRUE, TRUE, 0);
  263.     gtk_widget_show (thing);
  264.  
  265.     subframe = gtk_frame_new (NULL);
  266.     gtk_box_pack_start (GTK_BOX (the_led), subframe, TRUE, TRUE, 0);
  267.     gtk_widget_show (subframe);
  268.     thing = gtk_preview_new (GTK_PREVIEW_COLOR);
  269.     gtk_container_add (GTK_CONTAINER (subframe), thing);
  270.     led_widgets[nr] = thing;
  271.     gtk_signal_connect (GTK_OBJECT (thing), "event",
  272.             (GtkSignalFunc) driveled_event, (gpointer) thing);
  273.     gtk_widget_show (thing);
  274.  
  275.     thing = gtk_preview_new (GTK_PREVIEW_COLOR);
  276.     gtk_box_pack_start (GTK_BOX (the_led), thing, TRUE, TRUE, 0);
  277.     gtk_widget_show (thing);
  278.     
  279.     return the_led;
  280. }
  281.  
  282. static void *gtk_penguin (void *dummy)
  283. {
  284.     GtkWidget *window;
  285.     GtkWidget *buttonbox, *vbox;
  286.     GtkWidget *thing;
  287.  
  288.     int i;
  289.  
  290.     int argc = 1;
  291.     char *a[] = {"UAE"};
  292.     char **argv = a;
  293.  
  294.     gtk_init (&argc, &argv);
  295.     gtk_rc_parse ("uaegtkrc");
  296.  
  297.     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  298.     gtk_widget_set_name (window, "UAE control");
  299.  
  300.     led_bufs[0] = led_bufs[1] = led_bufs[2] = led_bufs[3] = led_bufs[4] = 0;
  301.  
  302.     vbox = gtk_vbox_new (FALSE, 4);
  303.     gtk_container_add (GTK_CONTAINER (window), vbox);
  304.  
  305.     /* Make a box with the Reset/Debug/Quit buttons and place it at the top
  306.      * of our vbox.  */
  307.     buttonbox = gtk_hbox_new (FALSE, 4);
  308.     thing = gtk_button_new_with_label ("Reset");
  309.     gtk_signal_connect (GTK_OBJECT (thing), "clicked", (GtkSignalFunc) did_reset, NULL);
  310.     gtk_box_pack_start (GTK_BOX (buttonbox), thing, FALSE, TRUE, 0);
  311.     gtk_widget_show (thing);
  312.     thing = gtk_button_new_with_label ("Debug");
  313.     gtk_signal_connect (GTK_OBJECT (thing), "clicked", (GtkSignalFunc) did_debug, NULL);
  314.     gtk_box_pack_start (GTK_BOX (buttonbox), thing, FALSE, TRUE, 0);
  315.     gtk_widget_show (thing);
  316.     thing = gtk_button_new_with_label ("Quit");
  317.     gtk_signal_connect (GTK_OBJECT (thing), "clicked", (GtkSignalFunc) did_quit, NULL);
  318.     gtk_box_pack_start (GTK_BOX (buttonbox), thing, FALSE, TRUE, 0);
  319.     gtk_widget_show (thing);
  320.     thing = make_led (4);
  321.     gtk_box_pack_start (GTK_BOX (buttonbox), thing, FALSE, TRUE, 0);
  322.     gtk_widget_show (thing);
  323.     gtk_box_pack_start (GTK_BOX (vbox), buttonbox, FALSE, TRUE, 0);
  324.     gtk_widget_show (buttonbox);
  325.  
  326.     /* Place a separator below those three buttons.  */
  327.     thing = gtk_hseparator_new ();
  328.     gtk_box_pack_start (GTK_BOX (vbox), thing, FALSE, TRUE, 0);
  329.     gtk_widget_show (thing);
  330.  
  331.     /* Now, the floppy disk control.  */
  332.     for (i = 0; i < 4; i++) {
  333.     GtkWidget *subthing, *subframe;
  334.     char buf[5];
  335.     sprintf (buf, "DF%d:", i);
  336.  
  337.     /* Each line: a frame with a hbox in it. The hbox contains
  338.      * the LED, the name of the drive and the diskfile in it, an
  339.      * Insert button, and an Eject button.  */
  340.     buttonbox = gtk_frame_new (buf);
  341.     thing = gtk_hbox_new (FALSE, 4);
  342.     gtk_container_add (GTK_CONTAINER (buttonbox), thing);
  343.         gtk_box_pack_start (GTK_BOX (vbox), buttonbox, FALSE, TRUE, 0);
  344.     gtk_widget_show (buttonbox);
  345.     gtk_widget_show (thing);
  346.     buttonbox = thing;
  347.  
  348.     subthing = make_led (i);
  349.     gtk_box_pack_start (GTK_BOX (buttonbox), subthing, FALSE, TRUE, 0);
  350.  
  351.     /* Make the "DF0:xxx" label.  */
  352.     subframe = gtk_frame_new (NULL);
  353.     gtk_frame_set_shadow_type (GTK_FRAME (subframe), GTK_SHADOW_ETCHED_OUT);
  354.     gtk_box_pack_start (GTK_BOX (buttonbox), subframe, FALSE, TRUE, 0);
  355.     gtk_widget_show (subframe);
  356.  
  357.     subthing = gtk_vbox_new (FALSE, 0);
  358.     gtk_container_add (GTK_CONTAINER (subframe), subthing);
  359.     gtk_widget_show (subthing);
  360.  
  361.     /* First, an invisible preview widget to set the horizontal size.  */
  362.     thing = gtk_preview_new (GTK_PREVIEW_COLOR);
  363.     gtk_widget_set_usize (thing, gdk_string_measure (subframe->style->font, "This is a very long name for a disk file, should be enough") + 7, 0);
  364.     gtk_widget_show (thing);
  365.     gtk_box_pack_start (GTK_BOX (subthing), thing, FALSE, TRUE, 0);
  366.  
  367.     /* Then, a label with the filename.  */
  368.     thing = gtk_label_new ("frebnisia");
  369.     disk_text_widget[i] = thing;
  370.     gtk_widget_show (thing);
  371.     gtk_box_pack_start (GTK_BOX (subthing), thing, FALSE, TRUE, 0);
  372.     
  373.     /* Now, the buttons.  */
  374.     thing = gtk_button_new_with_label ("Eject");
  375.     gtk_box_pack_start (GTK_BOX (buttonbox), thing, FALSE, TRUE, 0);
  376.     gtk_widget_show (thing);
  377.     disk_eject_widget[i] = thing;
  378.     gtk_signal_connect (GTK_OBJECT (thing), "clicked",
  379.                 (GtkSignalFunc) (i == 0 ? did_eject_0 
  380.                          : i == 1 ? did_eject_1 
  381.                          : i == 2 ? did_eject_2 : did_eject_3),
  382.                 NULL);
  383.  
  384.     thing = gtk_button_new_with_label ("Insert");
  385.     gtk_box_pack_start (GTK_BOX (buttonbox), thing, FALSE, TRUE, 0);
  386.     gtk_widget_show (thing);
  387.     disk_insert_widget[i] = thing;
  388.     gtk_signal_connect (GTK_OBJECT (thing), "clicked",
  389.                 (GtkSignalFunc) (i == 0 ? did_insert_0 
  390.                          : i == 1 ? did_insert_1 
  391.                          : i == 2 ? did_insert_2 : did_insert_3),
  392.                 NULL);
  393.     }
  394.  
  395.     enable_disk_buttons (1);
  396.  
  397.     gtk_widget_show (vbox);
  398.     gtk_widget_show (window);
  399.  
  400.     gtk_timeout_add (1000, (GtkFunction)my_idle, 0);
  401.     gtk_main ();
  402.     
  403.     quitted_gui = 1;
  404.     uae_sem_post (&gui_quit_sem);
  405.     return 0;
  406. }
  407.  
  408. void gui_changesettings(void)
  409. {
  410.     
  411. }
  412.  
  413. int gui_init(void)
  414. {
  415.     penguin_id tid;
  416.  
  417.     init_comm_pipe (&to_gui_pipe, 20, 1);
  418.     init_comm_pipe (&from_gui_pipe, 20, 1);
  419.     uae_sem_init (&gui_sem, 0, 1);
  420.     uae_sem_init (&gui_quit_sem, 0, 0);
  421.     start_penguin (gtk_penguin, NULL, &tid);
  422.     return 1;
  423. }
  424.  
  425. int gui_update(void)
  426. {
  427.     return 0;
  428. }
  429.  
  430. void gui_exit(void)
  431. {
  432.     quit_gui = 1;
  433.     uae_sem_wait (&gui_quit_sem);
  434. }
  435.  
  436. void gui_led(int num, int on)
  437. {
  438. /*    if (num == 0)
  439.     return;
  440.     printf("LED %d %d\n", num, on);
  441.     write_comm_pipe_int (&to_gui_pipe, 1, 0);
  442.     write_comm_pipe_int (&to_gui_pipe, num == 0 ? 4 : num - 1, 0);
  443.     write_comm_pipe_int (&to_gui_pipe, on, 1);
  444.     printf("#LED %d %d\n", num, on);
  445.    */ 
  446. }
  447.  
  448. void gui_filename(int num, const char *name)
  449. {
  450.     write_comm_pipe_int (&to_gui_pipe, 0, 0);
  451.     write_comm_pipe_int (&to_gui_pipe, num, 1);
  452.     
  453.     gui_update ();
  454. }
  455.  
  456. void gui_handle_events(void)
  457. {
  458.     while (comm_pipe_has_data (&from_gui_pipe)) {
  459.     int cmd = read_comm_pipe_int_blocking (&from_gui_pipe);
  460.     int n;
  461.     switch (cmd) {
  462.      case 0:
  463.         n = read_comm_pipe_int_blocking (&from_gui_pipe);
  464.         changed_prefs.df[n][0] = '\0';
  465.         break;
  466.      case 1:
  467.         n = read_comm_pipe_int_blocking (&from_gui_pipe);
  468.         uae_sem_wait (&gui_sem);
  469.         strncpy (changed_prefs.df[n], new_disk_string[n], 255);
  470.         changed_prefs.df[n][255] = '\0';
  471.         uae_sem_post (&gui_sem);
  472.         break;
  473.      case 2:
  474.         uae_reset ();
  475.         break;
  476.      case 3:
  477.         activate_debugger ();
  478.         break;
  479.      case 4:
  480.         uae_quit ();
  481.         break;
  482.     }
  483.     }
  484.     
  485. }
  486.